package com.wzb.mybatisplus.bitaction.formal;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.*;

public class BitcoinBatchBalanceChecker {

    private static final String BLOCKCYPHER_API = "https://api.blockcypher.com/v1/btc/main/addrs/";
    private static final ObjectMapper mapper = new ObjectMapper();
    private static final int MAX_CONCURRENT_REQUESTS = 5; // 控制并发数
    private static final int REQUEST_TIMEOUT = 10; // 秒

    // 余额结果类
    public static class BalanceResult {
        private String address;
        private long balanceSatoshi;
        private double balanceBtc;
        private boolean success;
        private String errorMessage;

        // 构造函数、getter、setter
        public BalanceResult(String address) {
            this.address = address;
        }

        // getter 和 setter 方法
        public String getAddress() { return address; }
        public long getBalanceSatoshi() { return balanceSatoshi; }
        public void setBalanceSatoshi(long balanceSatoshi) {
            this.balanceSatoshi = balanceSatoshi;
            this.balanceBtc = satoshiToBtc(balanceSatoshi);
        }
        public double getBalanceBtc() { return balanceBtc; }
        public boolean isSuccess() { return success; }
        public void setSuccess(boolean success) { this.success = success; }
        public String getErrorMessage() { return errorMessage; }
        public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }

        private double satoshiToBtc(long satoshi) {
            return satoshi / 100_000_000.0;
        }
    }

    // 单个地址查询任务
    private static class BalanceQueryTask implements Callable<BalanceResult> {
        private String address;

        public BalanceQueryTask(String address) {
            this.address = address;
        }

        @Override
        public BalanceResult call() {
            BalanceResult result = new BalanceResult(address);

            try (CloseableHttpClient client = HttpClients.createDefault()) {
                String apiUrl = BLOCKCYPHER_API + address + "/balance";
                HttpGet request = new HttpGet(apiUrl);

                try (CloseableHttpResponse response = client.execute(request)) {
                    String responseBody = EntityUtils.toString(response.getEntity());

                    if (response.getStatusLine().getStatusCode() == 200) {
                        JsonNode jsonNode = mapper.readTree(responseBody);
                        long balance = jsonNode.get("balance").asLong();
                        long unconfirmedBalance = jsonNode.has("unconfirmed_balance") ?
                                jsonNode.get("unconfirmed_balance").asLong() : 0;

                        result.setBalanceSatoshi(balance + unconfirmedBalance);
                        result.setSuccess(true);
                    } else {
                        result.setSuccess(false);
                        result.setErrorMessage("HTTP " + response.getStatusLine().getStatusCode());
                    }
                }
            } catch (Exception e) {
                result.setSuccess(false);
                result.setErrorMessage(e.getMessage());
            }

            return result;
        }
    }

    // 批量查询方法
    public static List<BalanceResult> batchQueryBalances(List<String> addresses) {
        List<BalanceResult> results = Collections.synchronizedList(new ArrayList<>());
        ExecutorService executor = Executors.newFixedThreadPool(MAX_CONCURRENT_REQUESTS);

        try {
            // 创建任务列表
            List<Callable<BalanceResult>> tasks = new ArrayList<>();
            for (String address : addresses) {
                tasks.add(new BalanceQueryTask(address));
            }

            // 执行所有任务，设置超时
            List<Future<BalanceResult>> futures = executor.invokeAll(tasks, REQUEST_TIMEOUT, TimeUnit.SECONDS);

            // 收集结果
            for (int i = 0; i < futures.size(); i++) {
                try {
                    BalanceResult result = futures.get(i).get();
                    results.add(result);
                } catch (Exception e) {
                    BalanceResult errorResult = new BalanceResult(addresses.get(i));
                    errorResult.setSuccess(false);
                    errorResult.setErrorMessage("Task execution failed: " + e.getMessage());
                    results.add(errorResult);
                }
            }

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            executor.shutdown();
        }

        return results;
    }

    public static void main(String[] args) {
        // 测试地址列表
        List<String> addresses = Arrays.asList(
//                "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
//                "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy",
//                "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
//                "1CounterpartyXXXXXXXXXXXXXXXUWLpVr",
//                "1BitcoinEaterAddressDontSendf59kuE",
//                "1HQ3Go3ggs8pFnXuHVHRytPCq5fGG8Hbhx",
//                "1MDUoxL1bGvMxhuoDYx6i11ePytECAk9QK",
//                "1CjPR7Z5ZSyWk6WtXvSFgkptmpoi4UM9BC",
                "1FeexV6bAHb8ybZjqQMjJrcCrHGW9sb6uF",
                "1JLg6ALxKs6V2xRPLdoeEa2NvZ1eowAkA8",
                "1Nv6rdJ1fT2yr5L2Hf81YwHfS6pM6rGj6q",
                "1BPcYkDBaQ9mT4XZ2qYA7j9KQ9Qh2w2J2W"
        );

        System.out.println("开始批量查询比特币余额...");
        long startTime = System.currentTimeMillis();

        List<BalanceResult> results = batchQueryBalances(addresses);

        long endTime = System.currentTimeMillis();

        // 输出结果
        System.out.println("查询完成，耗时: " + (endTime - startTime) + "ms");
        System.out.println("=====================================");

        for (BalanceResult result : results) {
            System.out.println("地址: " + result.getAddress());
            if (result.isSuccess()) {
                System.out.println("余额: " + result.getBalanceSatoshi() + " 聪");
                System.out.println("余额: " + String.format("%.8f", result.getBalanceBtc()) + " BTC");
            } else {
                System.out.println("查询失败: " + result.getErrorMessage());
            }
            System.out.println("-------------------------------------");
        }
    }
}